#include <iostream>
using namespace std;

#include "mySolution.h"
#include "myTwoOpt.h"

myTwoOpt::myTwoOpt()
  : edaMove(), graph (NULL)
{
}

myTwoOpt::myTwoOpt(const Graph &g)
  : edaMove(), graph (new Graph(g))
{
}

myTwoOpt::myTwoOpt(const myTwoOpt &move) : 
  pair<unsigned int, unsigned int> (move),
  edaMove(move)
{
  graph = new Graph(*(move.graph));
}

myTwoOpt::~myTwoOpt()
{
  if (graph != NULL)
  {
    delete graph;
  }
}

edaMove* myTwoOpt::clone() const
{
  return new myTwoOpt(*this);
}

void myTwoOpt::init(const edaSolution &sol)
{
  this->first = 0;
  this->second = 2;
}

double myTwoOpt::incrEval(const edaSolution &sol)
{
  mySolution &route = (mySolution &) sol;

  unsigned int v1 = route[this->first];
  unsigned int v1_next = route[this->first + 1];
  unsigned int v2 = route[this->second];
  unsigned int v2_next = route[this->second + 1];

  return route.fullEvaluate()
    - graph->distance(v1, v2)
    - graph->distance(v1_next, v2_next)
    + graph->distance(v1, v1_next)
    + graph->distance(v2, v2_next);
}

void myTwoOpt::update( edaSolution &sol ) const
{
  mySolution &mysol = (mySolution &)sol;

  vector<unsigned int> seq_cities;

  for (unsigned int i = second; i > first; i--)
  {
    seq_cities.push_back(mysol[i]);
  }
  
  unsigned int j = 0;
  for (unsigned int i = first + 1; i <= second; i++) {
    mysol[i] = seq_cities[j++];
  }

  // request the re-evaluation of fitness
  mysol.setModified();
}

void myTwoOpt::Serialize( edaBuffer &buf, bool pack )
{
  edaMove::Serialize( buf, pack );

  if ( pack )
  {
    graph->doSerialize(buf, pack);
  }
  else
  {
    if (graph != NULL)
    {
      delete graph;
    }
    graph = (Graph *)classGenerateFromBuffer(buf);
  }
}

edaMove& myTwoOpt::operator = (const edaMove& _move)
{
  this->first = ((myTwoOpt&)_move).first;
  this->second = ((myTwoOpt&)_move).second;

  return (*this);
}

bool myTwoOpt::operator == (const edaMove &_move) const
{
  return (*this) == _move;
}
